import * as THREE from 'three';
import { Debug } from './Debug';

interface Collider {
  object: THREE.Object3D;
  size: THREE.Vector3;
  position: THREE.Vector3;
  rotation: number;
  type: string;
}

export class PhysicsWorld {
  private colliders: Collider[] = [];
  private gravity: number = 9.81;
  private enabled: boolean = true;

  constructor() {
    Debug.log('物理系统已初始化');
  }

  // 统一的碰撞体添加方法
  public addCollider(
    object: THREE.Object3D,
    size: THREE.Vector3,
    position: THREE.Vector3,
    rotation: number = 0,
    type: string = 'default'
  ): Collider {
    return this.addBoxCollider(object, size, position, rotation, type);
  }

  public addBoxCollider(
    object: THREE.Object3D,
    size: THREE.Vector3,
    position: THREE.Vector3,
    rotation: number = 0,
    type: string = 'default'
  ): Collider {
    const collider: Collider = {
      object,
      size,
      position: position.clone(),
      rotation,
      type
    };

    this.colliders.push(collider);
    Debug.log(`添加碰撞体: ${type}`);
    return collider;
  }

  // 添加球形碰撞体
  public addSphereCollider(
    object: THREE.Object3D,
    radius: number,
    position: THREE.Vector3,
    rotation: number = 0,
    type: string = 'default'
  ): Collider {
    // 球形碰撞体使用立方体近似，大小为直径
    const size = new THREE.Vector3(radius * 2, radius * 2, radius * 2);
    return this.addBoxCollider(object, size, position, rotation, type);
  }

  public removeCollider(collider: Collider): void {
    const index = this.colliders.indexOf(collider);
    if (index !== -1) {
      this.colliders.splice(index, 1);
      Debug.log(`移除碰撞体: ${collider.type}`);
    }
  }

  public updateCollider(collider: Collider, position: THREE.Vector3, rotation: number): void {
    if (!collider) return;
    
    collider.position.copy(position);
    collider.rotation = rotation;
  }

  public checkCollision(position: THREE.Vector3, radius: number, type: string, debug: boolean = false): boolean {
    if (debug) {
      Debug.log(`检查碰撞: 位置(${position.x.toFixed(1)}, ${position.y.toFixed(1)}, ${position.z.toFixed(1)}), 半径: ${radius}, 类型: ${type}`);
    }
    
    for (const collider of this.colliders) {
      // 跳过同类型的碰撞体（例如玩家不会与玩家碰撞）
      if (collider.type === type) continue;
      
      // 简单的圆形碰撞检测
      const distance = position.distanceTo(collider.position);
      
      // 计算最小距离，使用碰撞体的一半大小
      const minDistance = radius + Math.max(collider.size.x, collider.size.z) / 2.5;
      
      if (debug) {
        Debug.log(`  与${collider.type}碰撞体距离: ${distance.toFixed(2)}, 最小距离: ${minDistance.toFixed(2)}`);
      }
      
      if (distance < minDistance) {
        if (debug) Debug.log(`  碰撞检测到: ${collider.type}`);
        return true;
      }
    }
    
    return false;
  }

  public checkProjectileCollision(position: THREE.Vector3, radius: number, targetType: string): boolean {
    return this.checkCollision(position, radius, targetType);
  }

  /**
   * 使用射线检测是否有障碍物
   * @param origin 起始位置
   * @param direction 方向向量
   * @param distance 最大检测距离
   * @returns 是否检测到障碍物
   */
  public raycastObstacle(origin: THREE.Vector3, direction: THREE.Vector3, distance: number): boolean {
    // 确保方向向量已标准化
    const dir = direction.clone().normalize();
    
    for (const collider of this.colliders) {
      // 跳过不需要作为障碍物的类型
      if (collider.type === 'player' || collider.type === 'projectile' || collider.type === 'power-up') {
        continue;
      }
      
      // 盒子中心点
      const center = collider.position.clone();
      
      // 从起点到盒子中心的向量
      const originToCenter = center.clone().sub(origin);
      
      // 向量在射线方向上的投影长度
      const projectionLength = originToCenter.dot(dir);
      
      // 如果投影在射线后方或超出最大距离，则不会相交
      if (projectionLength < 0 || projectionLength > distance) {
        continue;
      }
      
      // 计算从射线到盒子中心的最短距离
      const projection = dir.clone().multiplyScalar(projectionLength);
      const closestPoint = origin.clone().add(projection);
      const centerToClosest = closestPoint.clone().sub(center);
      
      // 计算碰撞体边界框的半尺寸
      const halfSize = collider.size.clone().multiplyScalar(0.5);
      
      // 检查最近点是否在碰撞体内
      if (Math.abs(centerToClosest.x) <= halfSize.x &&
          Math.abs(centerToClosest.y) <= halfSize.y &&
          Math.abs(centerToClosest.z) <= halfSize.z) {
        
        Debug.log(`射线检测到障碍物 (类型: ${collider.type}), 距离: ${projectionLength.toFixed(2)}`);
        return true;
      }
    }
    
    return false;
  }

  public update(deltaTime: number): void {
    if (!this.enabled) return;

    // 更新物理状态
    for (const collider of this.colliders) {
      // 应用重力
      if (!collider.object.userData.isStatic) {
        collider.position.y -= this.gravity * deltaTime;
        
        // 防止物体落到地面以下
        if (collider.position.y < 0) {
          collider.position.y = 0;
        }
      }

      // 更新物体位置
      collider.object.position.copy(collider.position);
      collider.object.rotation.y = collider.rotation;
    }
  }

  public setEnabled(enabled: boolean): void {
    this.enabled = enabled;
    Debug.log(`物理系统: ${enabled ? '启用' : '禁用'}`);
  }

  public dispose(): void {
    this.colliders = [];
    Debug.log('物理系统已清理');
  }
} 